package org.example.security.utils;

import org.example.core.constant.TokenConstants;
import org.example.core.exception.ExceptionCode;
import org.example.core.exception.auth.AuthorizeException;
import org.example.core.to.LoginUser;
import org.example.redis.service.RedisService;
import org.example.security.annotation.PermissionType;
import org.example.security.annotation.RequirePermission;
import org.example.security.annotation.RequireRole;
import org.example.security.constant.SecurityRedisConstants;
import org.example.security.handler.SecurityHandler;

import java.util.Set;

/**
 * @author 小杰_cc
 * @version 1.0
 */
public class AuthorizeUtil {

    private RedisService redisService;

    public AuthorizeUtil(RedisService redisService) {
        this.redisService = redisService;
    }

    /**
     * 判断是否为超级管理员
     */
    private boolean checkAdmin(Set<String> roles){
        return roles.contains(TokenConstants.SUPER_ADMIN);
    }

    /**
     * 判断是具有全部权限
     */
    private boolean checkPerms(Set<String> perms){
        return perms.contains(TokenConstants.ALL_PERMISSION);
    }

    private LoginUser getLoginUser(){
        String userId = SecurityHandler.getData().get(TokenConstants.USER_ID);
        LoginUser loginUser = redisService.getObject(SecurityRedisConstants.USER_TOKEN + userId);

        if (loginUser == null){
            throw new AuthorizeException(ExceptionCode.UNAUTHORIZED.getCode(), ExceptionCode.UNAUTHORIZED.getMsg());
        }
        return loginUser;
    }

    /**
     * 校验权限
     */
    public void checkPermission(RequirePermission requirePermission){
        LoginUser loginUser = getLoginUser();
        // 权限集合
        Set<String> permissions = loginUser.getPermissions();

        if (checkPerms(permissions)) return;

        if (requirePermission.type() == PermissionType.AND){
            checkAuthorizeAll(permissions,requirePermission.value());
        }

        if (requirePermission.type() == PermissionType.OR){
            checkAuthorizeOne(permissions, requirePermission.value());
        }
    }

    /**
     * 需要具有全部权限
     */
    private void checkAuthorizeAll(Set<String> authorizes, String... annotationValues){
        for (String value : annotationValues){
            if (!checkAuthorize(authorizes, value)){
                // 有一个不存在，抛异常
                throw new AuthorizeException(ExceptionCode.UNAUTHORIZED.getCode(), ExceptionCode.UNAUTHORIZED.getMsg());
            }
        }
    }

    /**
     * 值需要一个
     */
    private void checkAuthorizeOne(Set<String> authorizes, String... annotationValues){
        for (String value : annotationValues){
            if (checkAuthorize(authorizes, value)){
                return;
            }
        }
        // 循环结束没有一个，抛异常
        throw new AuthorizeException(ExceptionCode.UNAUTHORIZED.getCode(), ExceptionCode.UNAUTHORIZED.getMsg());
    }

    /**
     * 角色校验
     */
    public void checkRole(RequireRole requireRole) {
        LoginUser loginUser = getLoginUser();
        // 角色集合
        Set<String> roles = loginUser.getRoles();

        if (checkAdmin(roles)) return;

        if (requireRole.type() == PermissionType.AND){
            checkAuthorizeAll(roles,requireRole.value());
        }

        if (requireRole.type() == PermissionType.OR){
            checkAuthorizeOne(roles, requireRole.value());
        }
    }

    /**
     * 鉴权
     */
    public boolean checkAuthorize(Set<String> authorizes, String value){
        return authorizes.contains(value);
    }
}
